/*
 * Copyright (c) 2018-2023 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include "common.h"
#include "jm.h"

static struct hostNode *find_node_byfrom(in_addr_t);

void
initialize_master(void)
{
    HASH_WALK_T walk;
    char *key;
    struct hostNode *host;
    gf_hash_walk_start(gptrMyCluster->node_table, &walk);
    while (NULL != (host=(struct hostNode *)gf_hash_walk(&walk, &key))) {

        if (host == gptrMyHost) {
            continue;
        }

        if (host->server == CLIENT) {
            continue;
        }

        host->status[0] |= NRM_UNAVAIL;

        unsigned int j;
        for (j = 0; j < GET_INTNUM(gptrSharedConf->qpinfo->num_index); j++) {
            host->status[j + 1] = 0;
        }

        host->noload_count = 0;
        host->seq_number = 0;
    }
    gf_hash_walk_end(&walk);

    gptrMyCluster->boss_node = gptrMyHost;
    gptrMyCluster->number_inactivity = 0;
    gstrBossNode = copy_string(gptrMyHost->name);

    log_message(INFO, NOCLASS, "%s: I am the master now", __func__);

    return;
} // end function initialize_master

void
check_time_window(void)
{
    time_t timeNow = time(0);

    if (gptrMyHost->winclose_time > timeNow || 0 == gptrMyHost->winclose_time) {
        return;
    }

    struct dayhour dayhour;
    set_dayhour_4time(&dayhour, timeNow);


    bool_t active;
    active = iswindow_active(&dayhour, timeNow, &gptrMyHost->winclose_time, gptrMyHost->run_winlist);

    if (!active) {
        gptrMyHost->status[0] |= NRM_CLOSEWIN;
    } else {
        gptrMyHost->status[0] &= ~NRM_CLOSEWIN;
    }

    return;
}

int
is_clusteradmin(char *userName)
{
    unsigned int i;

    for (i = 0; i < gptrMyCluster->num_admins; i++) {
        if (strcmp(userName, gptrMyCluster->admins[i]) == 0)
            return TRUE;
    }

    return FALSE;
}

struct hostNode *
find_node_byaddr(struct sockaddr_in *from, const char *fname)
{
    if (from->sin_addr.s_addr == ntohl(LOOP_ADDR)) {
        return gptrMyHost;
    }

    struct hostent *hp;
    hp = gf_gethostbyaddr(&from->sin_addr.s_addr, sizeof(in_addr_t), AF_INET);
    if (hp == NULL) {
        char addrbuf[24+1];

        log_message(ERR, NOCLASS, "%s: gethostaddr() failed %s cannot by resolved by %s",
                    fname, gf_sockaddr_str(from, addrbuf), gptrMyHost->name);
        return NULL;
    }

    struct hostNode *host;
    host = (struct hostNode *)gf_hash_find(gptrMyCluster->node_table, hp->h_name);
    if (NULL != host) {
        return host;
    }

    host = find_node_byfrom(*(in_addr_t *)hp->h_addr_list[0]);
    if (NULL == host) {
        return NULL;
    }

    in_addr_t *nodeAddr;
    nodeAddr = (in_addr_t *)realloc(host->addr, (host->naddr + 1) * sizeof(in_addr_t));
    if (NULL == nodeAddr) {
        return host;
    }

    host->addr = nodeAddr;
    host->addr[host->naddr] = from->sin_addr.s_addr;
    host->naddr++;

    return host;
} // end function find_node_byaddr

static int
issame_addr(struct hostNode *node, u_int from)
{
    int i;

    for (i = 0; i < node->naddr; i++) {

        if (node->addr[i] == from)
            return TRUE;
    }

    return FALSE;
}

static struct hostNode *
find_node_byfrom(in_addr_t from)
{
    HASH_WALK_T walk;
    char *key;
    struct hostNode *host;
    gf_hash_walk_start(gptrMyCluster->node_table, &walk);
    while (NULL != (host=(struct hostNode *)gf_hash_walk(&walk, &key))) {

        if (issame_addr(host, from)) {
            return host;
        }
    }

    return NULL;
}
